package com.calvin.study.config.security;

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import com.calvin.study.config.security.jwt.JwtAuthenticationTokenFilter;
import com.calvin.study.service.sys.security.MyUserDetailsService;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	
	//自定义认证成功处理
	@Resource
	private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
	//自定义认证失败处理
	@Resource
	private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
	@Resource
	private MyUserDetailsService myUserDetailsService;
	@Resource
	private MyLogoutSuccessHandler myLogoutSuccessHandler;
	@Resource
	private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
	
	
	public void configure(HttpSecurity http) throws Exception {
		//.csrf()
		//.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
		//.ignoringAntMatchers("/authentication")
		http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
			.logout()
				.logoutUrl("/signout")
				.deleteCookies("JESSIONID")
				.logoutSuccessHandler(myLogoutSuccessHandler)
			.and().csrf().disable()
				.authorizeRequests()
				.antMatchers("/authentication","/refreshtoken").permitAll()//放行访问
				.antMatchers("/index").authenticated()
				.anyRequest().access("@rbacService.hasPermission(request,authentication)")//资源鉴权
			.and().sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
			;
	}
	
	//静态配置用户名/密码/角色
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
			auth.userDetailsService(myUserDetailsService)// 动态从数据中加载用户角色权限信息
				.passwordEncoder(passwordEncoder());// 配置BCrypt加密
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	//资源放行，不经过过滤器链
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/css/**","/fonts/**","/img/**","/js/**");
	}
	
	//AuthenticationManager注入 ，使用该Bean完成认证。
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}
